package com.yc.demo.exception;


import com.yc.demo.common.enums.ErrorCode;
import com.yc.demo.vo.ResultBody;

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;

/**
 * <p>统一异常处理器</p>
 *
 * @author YuanChilde
 * @version 1.0
 * Modification History:
 * Date    Author      Version     Description
 * -----------------------------------------------------------------
 * 2019-09-18 17:36    YuanChilde     1.0        新增
 * @date 2019-09-18 17:36
 */
@Slf4j
@RestControllerAdvice(basePackages = {"com.yc.demo"})
@Order(value = Ordered.HIGHEST_PRECEDENCE)
public class GlobalExceptionHandler {

    /**
     * Api异常处理
     * AuthenticationException
     *
     * @param ex
     * @param request
     * @param response
     *
     * @return
     */
    @ExceptionHandler( {ApiException.class})
    public static ResultBody apiException(Exception ex, HttpServletRequest request, HttpServletResponse response) {
        ResultBody resultBody = resolveException(ex);
        return resultBody;
    }

    @ExceptionHandler( {Exception.class})
    public static ResultBody exception(Exception ex, HttpServletRequest request, HttpServletResponse response) {
        ResultBody resultBody = resolveException(ex);
        return resultBody;
    }

    /**
     * 静态解析异常。可以直接调用
     *
     * @param ex
     *
     * @return
     */
    public static ResultBody resolveException(Exception ex) {
        ErrorCode code = ErrorCode.ERROR;
        String message = ex.getMessage();
        String className = ex.getClass().getName();
        if (className.contains("HttpMessageNotReadableException") || className.contains("TypeMismatchException") || className.contains(
                "MissingServletRequestParameterException")) {
            code = ErrorCode.BAD_REQUEST;
        } else if (className.contains("NoHandlerFoundException")) {
            code = ErrorCode.NOT_FOUND;
        } else if (className.contains("HttpRequestMethodNotSupportedException")) {
            code = ErrorCode.METHOD_NOT_ALLOWED;
        } else if (className.contains("HttpMediaTypeNotAcceptableException")) {
            code = ErrorCode.MEDIA_TYPE_NOT_ACCEPTABLE;
        } else if (className.contains("MethodArgumentNotValidException")) {
            BindingResult bindingResult = ((MethodArgumentNotValidException) ex).getBindingResult();
            code = ErrorCode.ALERT;
            return ResultBody.error(code.getCode(), bindingResult.getFieldError().getDefaultMessage());
        } else if (className.contains("IllegalArgumentException")) {
            code = ErrorCode.ALERT;
        } else if (StringUtils.isNotBlank(message) && message.equalsIgnoreCase(ErrorCode.TOO_MANY_REQUESTS.name())) {
            code = ErrorCode.TOO_MANY_REQUESTS;
        }
        return buildBody(ex, code);
    }

    /**
     * 构建返回结果对象
     *
     * @param exception
     *
     * @return
     */
    private static ResultBody buildBody(Exception exception, ErrorCode resultCode) {
        if (resultCode == null) {
            resultCode = ErrorCode.ERROR;
        }
        ResultBody resultBody = ResultBody.error(resultCode.getCode(), exception.getMessage());
        log.error("==> error:{} ", resultBody, exception);
        return resultBody;
    }

}
